package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.LearningRecordFormDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author leiyuhang
 * @since 2023-07-24
 */
@Service
@RequiredArgsConstructor
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {

    private final ILearningLessonService lessonService;
    private final LearningRecordMapper recordMapper;
    private final CourseClient courseClient;
    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {
        Long user = UserContext.getUser();
        LearningLesson learningLesson = lessonService.seleteByCourseIdAndUserId(user,courseId);
        if (learningLesson==null){
            return null;
        }
        LambdaQueryWrapper<LearningRecord> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LearningRecord::getUserId,user)
                .eq(LearningRecord::getLessonId,learningLesson.getId());
        List<LearningRecord> list = recordMapper.selectList(lambdaQueryWrapper);
        LearningLessonDTO lessonDTO = new LearningLessonDTO();
        lessonDTO.setId(learningLesson.getId());
        lessonDTO.setLatestSectionId(learningLesson.getLatestSectionId());
        lessonDTO.setRecords(BeanUtils.copyList(list, LearningRecordDTO.class));
        return lessonDTO;
    }

    @Override
    public void addLearningRecord(LearningRecordFormDTO formDTO) {
        // 1.获取登录用户
        Long userId = UserContext.getUser();
        // 2.处理学习记录
        boolean finished = false;
        if (formDTO.getSectionType() == SectionType.VIDEO) {
            // 2.1.处理视频
            finished = handleVideoRecord(userId, formDTO);
        }else{
            // 2.2.处理考试
            finished = handleExamRecord(userId, formDTO);
        }

        // 3.处理课表数据
        handleLearningLessonsChanges(formDTO, finished);
    }



    private void handleLearningLessonsChanges(LearningRecordFormDTO recordDTO, boolean finished) {
        // 1.查询课表
        LearningLesson lesson = lessonService.getById(recordDTO.getLessonId());
        if (lesson == null) {
            throw new BizIllegalException("课程不存在，无法更新数据！");
        }
        // 2.判断是否有新的完成小节
        boolean allLearned = false;
        if(finished){
            // 3.如果有新完成的小节，则需要查询课程数据
            CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
            if (cInfo == null) {
                throw new BizIllegalException("课程不存在，无法更新数据！");
            }
            // 4.比较课程是否全部学完：已学习小节 >= 课程总小节
            allLearned = lesson.getLearnedSections() + 1 >= cInfo.getSectionNum();
        }
        // 5.更新课表
        lessonService.lambdaUpdate()
                .set(lesson.getLearnedSections() == 0, LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .set(allLearned, LearningLesson::getStatus, LessonStatus.FINISHED.getValue())
                .set(!finished, LearningLesson::getLatestSectionId, recordDTO.getSectionId())
                .set(!finished, LearningLesson::getLatestLearnTime, recordDTO.getCommitTime())
                .setSql(finished, "learned_sections = learned_sections + 1")
                .eq(LearningLesson::getId, lesson.getId())
                .update();
    }

    private boolean handleExamRecord(Long userId, LearningRecordFormDTO formDTO) {
        LearningRecord record = BeanUtils.copyBean(formDTO, LearningRecord.class);
        record.setUserId(userId); record.setFinished(true);
        record.setFinishTime(formDTO.getCommitTime());
        boolean save = save(record);
        if (!save){
            throw  new DbException("新增考试失败");
        }
        return true;
    }

    private boolean handleVideoRecord(Long userId, LearningRecordFormDTO formDTO) {
        LearningRecord old = lambdaQuery().eq(LearningRecord::getUserId,userId)
                                          .eq(LearningRecord::getSectionId,formDTO.getSectionId()).one();
        if (old==null){
            LearningRecord record = BeanUtils.copyBean(formDTO, LearningRecord.class);
            record.setUserId(userId);
            boolean save = save(record);
            if (!save){
                throw  new DbException("新增播放失败");
            }
            return false;
        }
        boolean finished=!old.getFinished()&&formDTO.getMoment()*2>=formDTO.getDuration();
        boolean success = lambdaUpdate()
                .set(LearningRecord::getMoment, formDTO.getMoment())
                .set(finished, LearningRecord::getFinished, true)
                .set(finished, LearningRecord::getFinishTime, formDTO.getCommitTime())
                .eq(LearningRecord::getId, old.getId())
                .update();
        if(!success){
            throw new DbException("更新学习记录失败！");
        }
        return finished ;
    }


}
